home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / reduce.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  19.1 KB  |  744 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /* This file contains various functions needed for reduce actions */
  10.  
  11. #include "adared.h"
  12. #include "prsutilprots.h"
  13. #include "errsprots.h"
  14. #include "adalexprots.h"
  15. #include "pspansprots.h"
  16. #include "reduceprots.h"
  17.  
  18. static void pragma_warning(struct ast *);
  19. static void remove_link(struct ast *, struct two_pool **, struct two_pool *);
  20. static int in_label_set(struct ast *, struct two_pool *);
  21. static int is_pragma(int);
  22.  
  23. /* define PDEBUG to trace pragma procedures */
  24.  
  25.  
  26. void free_everything(struct ast *node)                /*;free_everything*/
  27. {
  28.     /* Recursively free all nodes in the tree beginning at node, and
  29.      * free all list structures and AST structures where they exist.
  30.      */
  31.  
  32.     struct two_pool *listptr;
  33.     int i;
  34.  
  35. #ifdef FDEBUG
  36.     if (trcopt)
  37.         fprintf(errfile,"Freeing node 0x%x, kind = %d\n",node,node->kind);
  38. #endif
  39.     /* check to see if the node has already been freed */
  40.     if (node->kind == AS_FREE)
  41.         return;
  42.     if (islist_node[node->kind]) {
  43. #ifdef FDEBUG
  44.         if (trcopt)
  45.             fprintf(errfile,"Traversing through list\n");
  46. #endif
  47.         if (node->links.list != NULL) {
  48.             listptr = node->links.list;
  49.             do {
  50.                 listptr = listptr->link;
  51.                 free_everything(listptr->val.node);
  52.             }        while (listptr != node->links.list);
  53.             TFREE(node->links.list->link,node->links.list);
  54.         }
  55.     }
  56.     else if (isast_node[node->kind]) {
  57. #ifdef FDEBUG
  58.         if (trcopt)
  59.             fprintf(errfile,"Traversing through tree\n");
  60. #endif
  61.         for (i = 0; i < MAX_AST && (node->links.subast)[i] != NULL; i++)
  62.             if ((node->links.subast)[i] != opt_node)
  63.                 free_everything((node->links.subast)[i]);
  64.         astfree(node->links.subast);
  65.     }
  66.     nodefree(node);
  67. #ifdef FDEBUG
  68.     if (trcopt)
  69.         fprintf(errfile,"Returning\n");
  70. #endif
  71. }
  72.  
  73. void set_span(struct ast *node, struct tok_loc *span)        /*;set_span*/
  74. {
  75.     /* Set the spans field of node to match the given spans. */
  76.     node->span.line = span->line;
  77.     node->span.col = span->col;
  78. }
  79.  
  80. struct two_pool *initlist(struct ast *node)                /*;initlist*/
  81. {
  82.     /* Allocate a single list structure (struct two_pool), set its data to
  83.      * be a pointer to the node given, and set its link field to point
  84.      * to itself, since tree node lists are circular.
  85.      */
  86.     struct two_pool *tmp;
  87.  
  88.     tmp = TALLOC();
  89.     tmp->val.node = node;
  90.     tmp->link = tmp;
  91.     return(tmp);
  92. }
  93.  
  94. struct ast **new_ast1(struct ast *a1)                    /*;new_ast1*/
  95. {
  96.     /* Allocate an array to hold pointers to the children of a node
  97.      * in the AST, and set elements of the array to the values given. This
  98.      * function may be called with fewer than the 4 parameters below, in which
  99.      * case the parameters given will be used properly, and undefined (garbage)
  100.      * values will be put in the latter part of the array.
  101.      */
  102.  
  103.     struct ast **tmp;
  104.  
  105.     tmp = astalloc();
  106.     tmp[0] = a1;
  107.     tmp[1] = 0;
  108.     tmp[2] = 0;
  109.     tmp[3] = 0;
  110.     return(tmp);
  111. }
  112.  
  113. struct ast **new_ast2(struct ast *a1, struct ast *a2)            /*;new_ast2*/
  114. {
  115.     struct ast **tmp;
  116.  
  117.     tmp = astalloc();
  118.     tmp[0] = a1;
  119.     tmp[1] = a2;
  120.     tmp[2] = 0;
  121.     tmp[3] = 0;
  122.     return(tmp);
  123. }
  124.  
  125. struct ast **new_ast3(struct ast *a1, struct ast *a2, struct ast *a3)
  126.                                                                 /*;new_ast3*/
  127. {
  128.     struct ast **tmp;
  129.  
  130.     tmp = astalloc();
  131.     tmp[0] = a1;
  132.     tmp[1] = a2;
  133.     tmp[2] = a3;
  134.     tmp[3] = 0;
  135.     return(tmp);
  136. }
  137.  
  138. struct ast **new_ast4(struct ast *a1, struct ast *a2, struct ast *a3,
  139.   struct ast *a4)                                                /*;new_ast4*/
  140. {
  141.     struct ast **tmp;
  142.  
  143.     tmp = astalloc();
  144.     tmp[0] = a1;
  145.     tmp[1] = a2;
  146.     tmp[2] = a3;
  147.     tmp[3] = a4;
  148.     return(tmp);
  149. }
  150.  
  151. struct two_pool *concatl(struct two_pool *bottom,struct two_pool *nextlist)
  152.                                                             /*;concatl*/
  153. {
  154.     /* Concatenate circular linked lists of structs of type two_pool
  155.      * together, returning the new end pointer. There are two such
  156.      * functions: concatl catenates two lists, concatl3 catenates three.
  157.      */
  158.     struct two_pool *tmp;
  159.  
  160.     if (bottom==(struct two_pool *)0) bottom = nextlist;
  161.     if (nextlist!=(struct two_pool *)0) {
  162.         tmp = bottom->link;
  163.         bottom->link = nextlist->link;
  164.         nextlist->link = tmp;
  165.         bottom = nextlist;
  166.     }
  167.     return(bottom);
  168. }
  169.  
  170. struct two_pool *concatl3(struct two_pool *bottom, struct two_pool *nextlist,
  171.   struct two_pool *list3)                                    /*;concatl3*/
  172. {
  173.     return concatl(concatl(bottom,nextlist),list3);
  174. }
  175.  
  176. void append(struct ast *orignode, struct ast *node)            /*;append*/
  177. {
  178.     /* Given two nodes from the AST, orignode with a list of children,
  179.      * and a new node node, allocate a new list structure for node and append
  180.      * it to the list of children, and set the spans of orignode so they remain
  181.      * correct.
  182.      */
  183.  
  184.     struct two_pool *tmp;
  185.  
  186.     tmp = TALLOC();
  187.     tmp->val.node = node;
  188.     if (orignode->links.list == (struct two_pool *)0)
  189.         tmp->link = tmp;
  190.     else {
  191.         tmp->link = orignode->links.list->link;
  192.         orignode->links.list->link = tmp;
  193.     }
  194.     orignode->links.list = tmp;
  195. }
  196.  
  197. void prepend(struct ast *node, struct ast *orignode)        /*;prepend*/
  198. {
  199.     /* Given two nodes from the AST, orignode with a list of children,
  200.      * and a new node node, allocate a new list structure for node and
  201.      * prepend it to the list of children, and set the spans of orignode
  202.      * so they remain correct.
  203.      */
  204.  
  205.     struct two_pool *tmp;
  206.  
  207.     tmp = TALLOC();
  208.     tmp->val.node = node;
  209.     if (orignode->links.list == (struct two_pool *)0)
  210.         orignode->links.list = tmp->link = tmp;
  211.     else {
  212.         tmp->link = orignode->links.list->link;
  213.         orignode->links.list->link = tmp;
  214.     }
  215. }
  216.  
  217. struct ast *binary_operator(struct ast *optr, struct ast *expr1,
  218.   struct ast *expr2)                                    /*;binary_operator*/
  219. {
  220.     /* Set up the AST node for a binary operator. */
  221.  
  222.     struct ast *node, *arg_list_node;
  223.     struct two_pool *tmp;
  224.  
  225.     NN(AS_OP);
  226.     arg_list_node = new_node(AS_LIST);
  227.     (arg_list_node->links.list = TALLOC())->val.node = expr2;
  228.     (arg_list_node->links.list->link = tmp = TALLOC())->val.node = expr1;
  229.     tmp->link = arg_list_node->links.list;
  230.     NAST2(optr,arg_list_node);
  231.     return(node);
  232. }
  233.  
  234. struct ast *unary_operator(struct ast *optr, struct ast *expr)
  235.                                                         /*;unary_operator*/
  236. {
  237.     /* Set up the AST node for a unary operator. */
  238.     struct ast *node, *arg_list_node;
  239.  
  240.     node = new_node(AS_UN_OP);
  241.     arg_list_node = new_node(AS_LIST);
  242.     arg_list_node->links.list = initlist(expr);
  243.     NAST2(optr,arg_list_node);
  244.     return(node);
  245. }
  246.  
  247. int check_expanded_name(struct ast *name)            /*;check_expanded_name*/
  248. {
  249.     /* Make sure an expanded name node is valid. */
  250.  
  251. #define sub_expanded_name ((name->links.subast)[0])
  252.     return((name->kind == AS_SELECTOR) ? 
  253.       check_expanded_name(sub_expanded_name) : (name->kind == AS_SIMPLE_NAME));
  254. #undef sub_expanded_name
  255. }
  256.  
  257. void check_discrete_range(struct ast *discrete_range) /*;check_discrete_range*/
  258. {
  259.     /* Check whether a discrete range node is valid. */
  260.  
  261.     switch (discrete_range->kind)
  262.     {
  263.     case AS_RANGE_EXPRESSION :
  264. #define name (discrete_range->links.subast)[0]
  265.         if (!check_expanded_name(name))
  266.             syntax_err(SPAN(discrete_range),
  267.               "Invalid discrete_range specification");
  268.         else
  269.             discrete_range->kind = AS_NAME;
  270.         break;
  271. #undef name
  272.     case AS_RANGE_ATTRIBUTE :
  273.     case AS_SUBTYPE :
  274.         break;
  275.     default :
  276.         syntax_err(SPAN(discrete_range),
  277.           "Invalid discrete_range specification");
  278.     }
  279. }
  280.  
  281. static void pragma_warning(struct ast *pragma_node)            /*;pragma_warning*/
  282. {
  283.     /* Give a warning that a pragma is ignored. */
  284.  
  285.     char msg[MAXLINE + 30];
  286.  
  287. #define id (pragma_node->links.subast)[0]
  288.     sprintf(msg,"Pragma %s is ignored", namelist(id->links.val));
  289.     prs_warning(SPAN(pragma_node),msg);
  290. #undef id
  291. }
  292.  
  293. void pragmalist_warning(struct ast *list_node)        /*;pragmalist_warning*/
  294. {
  295.     /* For all nodes in the list of list_node give a warning the the pragma
  296.      * is invalid.
  297.      */
  298.  
  299.     LLOOPTOP(list_node->links.list,tmp)
  300.         pragma_warning(tmp->val.node);
  301.     LLOOPBOTTOM(tmp)
  302. }
  303.  
  304. static void remove_link(struct ast *pragma_node, struct two_pool **current,
  305.   struct two_pool *prev)                                /*;remove_link*/
  306. {
  307.     /* Remove a node (pragma_node) from a circular linked list of nodes. */
  308.  
  309.     if ((*current)->link != *current)
  310.         prev->link = (*current)->link;
  311.     else
  312.         pragma_node->links.list = (struct two_pool *) 0;
  313.     nodefree((*current)->val.node);
  314.     TFREE(*current,*current);
  315.     *current = prev;
  316. }
  317.  
  318. void check_pragmas(struct ast *pragma_node, int (*allowed_test)(int))
  319.                                                     /*;check_pragmas*/
  320. {
  321.     /* Check that a pragma is valid. */
  322.  
  323.     struct two_pool *old_list, *prev, *current;
  324.     int id;
  325.     int last;
  326.  
  327. #ifdef PDEBUG
  328.     printf("enter check_pragmas\n");
  329. #endif
  330.     if ((old_list = prev = current = pragma_node->links.list) != 
  331.       (struct two_pool *)0)
  332.     {
  333.         do {
  334.             last = (current = current->link) == old_list;
  335.             id = (current->val.node->links.subast)[0]->links.val;
  336. #ifdef PDEBUG
  337.             printf("check_pragma id %d\n",id);
  338. #endif
  339.             if (is_pragma(id) && (*allowed_test)(id - MIN_PRAGMA)) {
  340.                 if (strcmp(namelist(id),"PRIORITY")
  341.                   && strcmp(namelist(id),"ELABORATE")
  342.                   && strcmp(namelist(id),"INTERFACE"))
  343.                 {
  344.                     pragma_warning(current->val.node);
  345.                     remove_link(pragma_node,¤t,prev);
  346.                 }
  347.             }
  348.             else if (is_pragma(id) && ispredef_pragma[id - MIN_PRAGMA])
  349.             {
  350.                 char msg[200];
  351.  
  352.                 sprintf(msg,"Pragma %s is not valid in this context",
  353.                   namelist(id));
  354.                 prs_warning(SPAN(current->val.node),msg);
  355.                 remove_link(pragma_node,¤t,prev);
  356.             }
  357.             else if (!(is_pragma(id) && isimpldef_pragma[id - MIN_PRAGMA])
  358.               && strcmp(namelist(id),"OPTIMIZE"))
  359.             {
  360.                 pragma_warning(current->val.node);
  361.                 remove_link(pragma_node,¤t,prev);
  362.             }
  363.             prev = current;
  364.         }    while (!last);
  365.     }
  366. }
  367.  
  368. int isoverloadable_op(char *str)                /*;isoverloadable_op*/
  369. {
  370.     /* Check whether a string represnts an overloadable operator by
  371.      * comparing against all overloadable operators.
  372.      */
  373.  
  374.     char tmp[MAXLINE + 1];
  375.     int i;
  376.  
  377.     strcpy(tmp,str);
  378.     convtolower(tmp);
  379.     for (i = 0; i < NUMOVERLOADOPS; i++)
  380.         if (!strcmp(tmp,overloadable_operators[i]))
  381.             return(1);
  382.     return(0);
  383. }
  384.  
  385. void make_id(int n)                                            /*;make_id*/
  386. {
  387.     /* Allocate a node for a simple name whose value and span are* known by
  388.      * looking at the nth symbol in the right hand side of the reduction,
  389.      * and set these fields.
  390.      */
  391.     id_node = new_node(AS_SIMPLE_NAME);
  392.     id_node->links.val = IND(n);
  393.     set_span(id_node,LOC(n));
  394. }
  395.  
  396.  
  397. /* The following functions are for passing to check_pragmas */
  398.  
  399. int immediate_decl_pragmas(int p)                /*;immediate_decl_pragmas*/
  400. {
  401. #ifdef PDEBUG
  402.     printf("enter immediate_decl pragmas %d %d\n",p,isimmediate_decl_pragma[p]);
  403. #endif
  404.     return(isimmediate_decl_pragma[p]);
  405. }
  406.  
  407. int compilation_pragmas(int p)                    /*;compilation_pragmas*/
  408. {
  409. #ifdef PDEBUG
  410.     printf("enter compilation pragmas %d %d\n",p,iscompilation_pragma[p]);
  411. #endif
  412.     return(iscompilation_pragma[p]);
  413. }
  414.  
  415. int after_libunit_pragmas(int p)                /*;after_libunit_pragmas*/
  416. {
  417. #ifdef PDEBUG
  418.     printf("enter after_libunit pragmas %d %d\n",p,isafter_libunit_pragma[p]);
  419. #endif
  420.     return(isafter_libunit_pragma[p]);
  421. }
  422.  
  423. int task_pragmas(int p)                            /*;task_pragmas*/
  424. {
  425. #ifdef PDEBUG
  426.     printf("enter istask pragmas %d %d\n",p,istask_pragma[p]);
  427. #endif
  428.     return(istask_pragma[p]);
  429. }
  430.  
  431. int task_repr_pragmas(int p)                    /*;task_repr_pragmas*/
  432. {
  433. #ifdef PDEBUG
  434.     int r;
  435.     r =(istask_pragma[p] || isrepr_pragma[p]);
  436.     printf("enter task_repr pragmas %d %d\n",p,r);
  437. #endif
  438.     return(istask_pragma[p] || isrepr_pragma[p]);
  439. }
  440.  
  441. int context_pragmas(int p)                        /*;context_pragmas*/
  442. {
  443. #ifdef PDEBUG
  444.     printf("enter context pragmas %d %d\n",p,iscontext_pragma[p]);
  445. #endif
  446.     return(iscontext_pragma[p]);
  447. }
  448.  
  449. int null_pragmas(int i)                                    /*;null_pragmas*/
  450. {
  451. #ifdef PDEBUG
  452.     printf("enter null pragmas \n");
  453. #endif
  454.     return(i = 0);
  455. }
  456.  
  457.  
  458. void check_choices(struct ast *alt_node, char *source)    /*;check_choices*/
  459. {
  460.     struct two_pool *others_indices = (struct two_pool *)0, 
  461.     *choice_list, *last_alt_list;
  462.     struct ast *last_alt = (struct ast *) 0;
  463.     int choice_flag = 0;
  464.  
  465.     LLOOPTOP(alt_node->links.list,tmp)
  466.         if (tmp->val.node->kind != AS_PRAGMA) {
  467.             choice_list = (tmp->val.node->links.subast)[0]->links.list;
  468.             if (choice_list->link != choice_list)   /* cannot be NULL */
  469.                 LLOOPTOP(choice_list,tmp2)
  470.                     if (tmp2->val.node->kind == AS_OTHERS
  471.                       || tmp2->val.node->kind == AS_OTHERS_CHOICE)
  472.                     {
  473.                         char msg[90];
  474.  
  475.                         sprintf(msg,"The choice OTHERS must appear alone in %s",
  476.                           source);
  477.                         syntax_err(SPAN(tmp2->val.node),msg);
  478.                         choice_flag = 1;
  479.                         break;
  480.                     }
  481.                 LLOOPBOTTOM(tmp2)
  482.                if (!choice_flag) {
  483.                 if (choice_list->link->val.node->kind == AS_OTHERS
  484.                   || choice_list->link->val.node->kind == AS_OTHERS_CHOICE)
  485.                     others_indices = concatl(others_indices,
  486.                       initlist(tmp->val.node));
  487.             }
  488.             else
  489.                 choice_flag = 0;
  490.             last_alt_list = tmp;
  491.         }
  492.     LLOOPBOTTOM(tmp)
  493.     last_alt = last_alt_list->val.node;
  494.     LLOOPTOP(others_indices,tmp)
  495.         {
  496.         struct ast *choice;
  497.         char msg[90];
  498.  
  499.         if (tmp->val.node == last_alt)
  500.             continue;
  501.         choice = (tmp->val.node->links.subast)[0]->links.list->link->val.node;
  502.         sprintf(msg,"The choice OTHERS must appear last in %s",source);
  503.         syntax_err(SPAN(choice),msg);
  504.     }
  505.     LLOOPBOTTOM(tmp)
  506.     if (others_indices != (struct two_pool *)0 )
  507.         TFREE(others_indices->link,others_indices);
  508. }
  509.  
  510. struct two_pool *remove_duplicate_labels(struct two_pool *label_list)
  511.                                             /*;remove_duplicate_labels*/
  512. {
  513.     struct two_pool *new_label_list = (struct two_pool *)0,
  514.     *label_id_set = (struct two_pool *)0;
  515.     struct ast *node, *label;
  516.  
  517.     LLOOPTOP(label_list,tmp)
  518.         if ((node = tmp->val.node)->kind == AS_SIMPLE_NAME) {
  519.             if (in_label_set(node,label_id_set))
  520.                 syntax_err(SPAN(node),"Duplicate label name");
  521.             else {
  522.                 /* new_label_list = concatl(new_label_list,initlist(node)); */
  523.                 label_id_set = concatl(label_id_set,initlist(node));
  524.             }
  525.             new_label_list = concatl(new_label_list,initlist(node));
  526.         }
  527.         else
  528.         LLOOPTOP(node->links.list,tmp2)
  529.             label = tmp2->val.node;
  530.         if (in_label_set(label,label_id_set))
  531.             syntax_err(SPAN(label),"Duplicate label name");
  532.         else
  533.             label_id_set = concatl(label_id_set,initlist(label));
  534.         LLOOPBOTTOM(tmp2)
  535.     LLOOPBOTTOM(tmp)
  536.     if (label_id_set != (struct two_pool *)0)
  537.         TFREE(label_id_set->link,label_id_set);
  538.     if (label_list != (struct two_pool *)0)
  539.         TFREE(label_list->link,label_list);
  540.     return(new_label_list);
  541. }
  542.  
  543. static int in_label_set(struct ast *label, struct two_pool *label_set)
  544.                                                         /*;in_label_set*/
  545. {
  546.     int val = label->links.val;
  547.  
  548.     LLOOPTOP(label_set,tmp)
  549.         if (tmp->val.node->links.val == val)
  550.             return(1);
  551.     LLOOPBOTTOM(tmp)
  552.     return(0);
  553. }
  554.  
  555. void ins_as_line_no(struct ast *node)                /*;ins_as_line_no*/
  556. {
  557.     /* insert as_line_no nodes before each item in declarative/stmt list */
  558.     struct two_pool *dec_list,
  559.     *prev,*bottom;
  560.     struct ast *line_node;
  561.     struct tok_loc *line_node_span;
  562.  
  563.  
  564.     if (node -> links.list != (struct two_pool *)0) {
  565.  
  566.         dec_list = bottom = node -> links.list;
  567.         do {
  568.             prev = dec_list;
  569.             dec_list = dec_list -> link;
  570.  
  571.             line_node = new_node (AS_LINE_NO);
  572.             line_node_span = get_left_span(dec_list->val.node);
  573.             line_node -> links.val = line_node_span->line;
  574.             set_span(line_node,line_node_span);
  575.             /* Insert a new node with the AS_LINE_NO between dec_list and its 
  576.                     predecessor */
  577.             prev -> link = initlist (line_node) ;
  578.             prev->link->link = dec_list;
  579.         } while (dec_list != bottom);
  580.     }
  581. }
  582.  
  583. void end_as_line_no(struct ast *list_node, struct prsstack *next_token)
  584.                                                     /*;end_as_line_no*/
  585. {
  586.     /* add an as_line_no node to end of statement list this is the line
  587.      * number of the token following the sequence of statements
  588.      */
  589.  
  590.     struct two_pool * last, * first;
  591.     struct ast        * line_node;
  592.  
  593.     if ( (last = list_node->links.list) != (struct two_pool *)0) {
  594.         first = last->link;
  595.         line_node = new_node (AS_LINE_NO);
  596.         line_node->links.val = next_token->ptr.token->loc.line ;
  597.         set_span(line_node,make_span(line_node->links.val,
  598.           next_token->ptr.token->loc.col));
  599.         last->link = initlist(line_node);
  600.         last->link->link = first;
  601.         list_node->links.list = last->link;
  602.     }
  603. }
  604.  
  605. #define LABELSMAPSIZE 50
  606.  
  607. struct labelsmap {
  608.     struct ast *node;
  609.     struct two_pool *list;
  610.     struct labelsmap *link;
  611. };
  612.  
  613. struct labelsmap *nodetolabelstable[LABELSMAPSIZE]; /* Table for Labels map */
  614. /* List of free label structures */
  615. static struct labelsmap *deadlabels = (struct labelsmap *)0;
  616.  
  617. unsigned long labelshash(struct ast *node)            /*;labelshash*/
  618. {
  619.     /* The hash function from nodes to integers */
  620.     return( ((unsigned long) node) % LABELSMAPSIZE);
  621. }
  622.  
  623. void newlabels(struct ast *node, struct two_pool *list)        /*;newlabels*/
  624. {
  625.     /* Add node to the map, and initialize its labels list to list.
  626.      * Storage allocation is done using malloc/free structure list.
  627.      */
  628.  
  629.     int pos;
  630.     struct labelsmap *labelnode;
  631.  
  632.     pos = (int)labelshash(node);
  633.     if (deadlabels == (struct labelsmap *)0)
  634.         labelnode = (struct labelsmap *)malloc(sizeof(struct labelsmap));
  635.     else {
  636.         labelnode = deadlabels;
  637.         deadlabels = deadlabels->link;
  638.     }
  639.     labelnode->link = nodetolabelstable[pos];
  640.     nodetolabelstable[pos] = labelnode;
  641.     labelnode->node = node;
  642.     labelnode->list = list;
  643. }
  644.  
  645. struct two_pool *getlabels(struct ast *node)                /*;getlabels*/
  646. {
  647.     /* Return the list of labels corresponding to a given node. If
  648.      * The map is not defined for a node, NULL is returned.
  649.      */
  650.  
  651.     struct labelsmap *tmp;
  652.  
  653.     for (tmp = nodetolabelstable[labelshash(node)];
  654.       tmp != (struct labelsmap *)0 && tmp->node != node; tmp = tmp->link);
  655.     return((tmp == (struct labelsmap *)0) ? (struct two_pool *)0 : tmp->list);
  656. }
  657.  
  658. void erase_labels(struct ast *node)                        /*;erase_labels*/
  659. {
  660.     /* Remove a node from the labels map, freeing the structure used for
  661.      * that node's labels.
  662.      */
  663.  
  664.     struct labelsmap *tmp, *last;
  665.     int pos;
  666.  
  667.     pos = (int)labelshash(node);
  668.     for (tmp = nodetolabelstable[pos], last = (struct labelsmap *)0; 
  669.       tmp != (struct labelsmap *)0 && tmp->node != node;
  670.       last = tmp, tmp = tmp->link);
  671.     if (tmp == (struct labelsmap *)0)
  672.         return;
  673.     if (last == (struct labelsmap *)0)
  674.         nodetolabelstable[pos] = tmp->link;
  675.     else
  676.         last->link = tmp->link;
  677.     tmp->link = deadlabels;
  678.     deadlabels = tmp;
  679.     if (tmp->list != (struct two_pool *)0)
  680.         TFREE(tmp->list->link,tmp->list);
  681. }
  682.  
  683. struct two_pool *copylist(struct two_pool *list)            /*;copylist*/
  684. {
  685.     /* Copy a circular linked list of structs of type two_pool leaving
  686.      * the data of the nodes intact.
  687.      */
  688.     struct two_pool *oldcurr, *newcurr, *top;
  689.  
  690.     if (list == (struct two_pool *)0)
  691.         return((struct two_pool *)0);
  692.     newcurr = top = TALLOC();
  693.     oldcurr = list->link;
  694.     top->val.node = oldcurr->val.node;
  695.     while (oldcurr != list) {
  696.         oldcurr = oldcurr->link;
  697.         newcurr->link = TALLOC();
  698.         newcurr = newcurr->link;
  699.         newcurr->val.node = oldcurr->val.node;
  700.     }
  701.     newcurr->link = top;
  702.     return(newcurr);
  703. }
  704.  
  705. void free_labels()                                            /*;free_labels*/
  706. {
  707.     /* Remove all entries in the labels map. */
  708.     int i;
  709.     struct labelsmap *curr;
  710.  
  711.     for (i = 0; i < LABELSMAPSIZE; i++)
  712.         if (nodetolabelstable[i] != (struct labelsmap *)0) {
  713.             for (curr = nodetolabelstable[i]; curr->link!=NULL; curr=curr->link)
  714.                 if (curr->list != NULL)
  715.                     TFREE(curr->list->link,curr->list);
  716.             curr->link = deadlabels;
  717.             deadlabels = nodetolabelstable[i];
  718.             nodetolabelstable[i] = NULL;
  719.         }
  720. }
  721.  
  722. #ifdef DEBUG
  723. /* for debugging use */
  724. void dump_labels(struct ast *node)                            /*;dump_labels*/
  725. {
  726.     struct labelsmap *tmp;
  727.     void zpnlist(struct two_pool *);
  728.  
  729.     for (tmp = nodetolabelstable[labelshash(node)];
  730.       tmp != NULL && tmp->node != node; tmp = tmp->link);
  731.     zpnlist(tmp->list);
  732. }
  733. #endif 
  734.  
  735. static int is_pragma(int n)                                 /*;is_pragma*/
  736. {
  737.     /* Metaware miscompiles if:
  738.     return (MIN_PRAGMA <= (n) && (n) <= MAX_PRAGMA);
  739.      * so reorder first test until MetaWare compiler bug fixed
  740.      */
  741.     return ((n)>=MIN_PRAGMA  && (n) <= MAX_PRAGMA);
  742. }
  743.  
  744.